﻿using EasyAdmin.Application.Contracts.Systems.Orgs;
using EasyAdmin.Application.Contracts.Systems.Orgs.Dtos;
using EasyAdmin.Application.Contracts.Systems.Roles.Dtos;
using EasyAdmin.Domain.Entities.Systems;
using EasyCore.Application;
using EasyCore.ObjectMapper;
using EasyCore.UnifyResult.Exceptions;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;

namespace EasyAdmin.Application.Systems
{
    /// <summary>
    /// 机构管理
    /// </summary>
    public class OrgAppService : AppService, IOrgAppService
    {
        /// <summary>
        /// 机构仓储
        /// </summary>
        private readonly ISqlSugarRepository<SysOrg> _orgRepo;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="orgRepo"></param>
        public OrgAppService(ISqlSugarRepository<SysOrg> orgRepo)
        {
            _orgRepo = orgRepo;
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<SqlSugarPagedList<OrgOutput>> Page(OrgPageCondition condition)
        {
            string parentOrgCode = null;
            if (condition.ParentOrgId.HasValue)
            {
                var org = await _orgRepo.FirstOrDefaultAsync(m => m.Id == condition.PageIndex);
                if (org == null) parentOrgCode = org.OrgCode;
            }
            var data = await _orgRepo.AsQueryable().LeftJoin<SysOrg>((m, a) => m.ParentId == a.Id).Where((m, a) => m.IsDeleted == false)
                .WhereIF(!string.IsNullOrWhiteSpace(condition.SearchText), (m, a) => m.Name.Contains(condition.SearchText) || m.FullName.Contains(condition.SearchText))
                .WhereIF(!string.IsNullOrWhiteSpace(parentOrgCode),(m,a)=>m.OrgCode.StartsWith(parentOrgCode))
                .Select((m, a) => new OrgOutput
                {
                    Id = m.Id,
                    ParentId = m.ParentId,
                    ParentOrgName = a.Name,              
                    Name = m.Name,
                    FullName = m.FullName,
                    OrgType = m.OrgType,
                    CreditCode = m.CreditCode,
                    Contacts = m.Contacts,
                    Telephone = m.Telephone,
                    Address = m.Address,
                    Notes = m.Notes,
                    OrderSort = m.OrderSort,
                    IsDisabled = m.IsDisabled
                }).OrderByDescending(m =>  m.OrderSort).ToPagedListAsync(condition.PageIndex, condition.PageSize);
            return data; throw new NotImplementedException();
        }

        /// <summary>
        /// 创建机构
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task CreateOrg(CreateUpdateOrgInput input)
        {
            var parentOrg = await _orgRepo.FirstOrDefaultAsync(m => m.Id == input.ParentId && m.IsDeleted == false); //父机构
            if (parentOrg == null) BusinessThrow.Throw("所属部门不存在，导致添加失败！");     
            var org = await _orgRepo.FirstOrDefaultAsync(m => (m.Name == input.Name || m.FullName == input.FullName) && m.IsDeleted == false);
            if (org != null) BusinessThrow.Throw("机构名称或全称已存在，导致添加失败！");
            if (!string.IsNullOrWhiteSpace(input.CreditCode))
            {
                org = await _orgRepo.FirstOrDefaultAsync(m => m.CreditCode == input.CreditCode && m.IsDeleted == false);
                if (org != null) BusinessThrow.Throw("统一信用代码已存在，导致添加失败！");
            }
            var subOrgs = await _orgRepo.ToListAsync(m => m.ParentId == input.ParentId && m.IsDeleted == false); //同级机构
            var deptCodes = subOrgs.Select(m => m.DeptCode).ToList();
            int deptCode = 9999;
            for (int index = 1; index < 100; index++)
            {
                if (!deptCodes.Contains(index)) continue;
                deptCode = index;
            }
            if (deptCode >= 100) BusinessThrow.Throw("同级部门已超过99个，导致添加失败！");
            var model = input.MapTo<SysOrg>();
            model.Level = parentOrg.Level + 1;
            model.OrgCode = string.Format("{0}.{1}", parentOrg.OrgCode, deptCode.ToString());
            model.DeptCode = deptCode;
            await _orgRepo.InsertAsync(org);
        }

        /// <summary>
        /// 更新机构
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateOrg(CreateUpdateOrgInput input)
        {
            var org = await _orgRepo.FirstOrDefaultAsync(m => m.Id == input.Id.Value);
            if (org == null) BusinessThrow.Throw("数据不存在，导致更新失败！");
            if (input.ParentId != org.ParentId) BusinessThrow.Throw("所属部门暂时无法做修改，导致更新失败！");
            var brother = await _orgRepo.FirstOrDefaultAsync(m => (m.Name == input.Name || m.FullName == input.FullName) && m.IsDeleted == false && m.Id != input.Id.Value && m.ParentId == org.ParentId);
            if (brother != null) BusinessThrow.Throw("机构名称或全称已存在，导致更新失败！");      
            if (!string.IsNullOrWhiteSpace(input.CreditCode))
            {
                org = await _orgRepo.FirstOrDefaultAsync(m => m.CreditCode == input.CreditCode && m.IsDeleted == false && m.Id != input.Id.Value);
                if (org != null) BusinessThrow.Throw("机构统一信用代码已存在");
            }
            org = input.MapTo<CreateUpdateOrgInput, SysOrg>(org);
            await _orgRepo.InsertAsync(org);
        }


        /// <summary>
        /// 删除机构
        /// </summary>
        /// <param name="orgId"></param>
        /// <returns></returns>
        public async Task DeleteOrg(long orgId)
        {
            var children = await _orgRepo.ToListAsync(m => m.ParentId == orgId && m.IsDeleted == false);
            if (children != null && children.Any())
            {
                BusinessThrow.Throw("当前机构存在下属子机构，导致删除失败！");
            }
            var org = await _orgRepo.FirstOrDefaultAsync(m => m.Id == orgId);
            if (org == null) BusinessThrow.Throw("数据不存在");
            await _orgRepo.DeleteAsync(org);
        }

        /// <summary>
        /// 创建机构
        /// </summary>
        /// <param name="orgId"></param>
        /// <returns></returns>
        public async Task<OrgOutput> GetOrgByOrgId(long orgId)
        {
            var org = await _orgRepo.FirstOrDefaultAsync(m => m.Id == orgId);
            if (org == null) BusinessThrow.Throw("数据不存在");
            return org.MapTo<OrgOutput>();
        }    
    }
}
